#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define Size 7

void InitBoard(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            Board[i][j] = '-'; // 下在 - 上
        }
    }
}

void PrintBoard(char (*Board)[Size])
{
    printf("     ");
    for (int i = 0; i < Size; i++)
    {
        printf("%4d ", i + 1);
    }
    printf("\n");
    for (int i = 0; i < Size; i++)
    {
        printf("%4d ", i + 1); // 在每一行打印前先打印数字
        for (int j = 0; j < Size; j++)
        {
            printf("%4c ", Board[i][j]);
        }
        printf("\n");
    }
}

bool MakeMove(char (*Board)[Size], int row, int col, char player)
{
    if (row < 0 || row >= Size || col < 0 || col >= Size)
    {
        printf("非法位置!请重新输入\n");
        return false;
    }
    if(Board[row][col]!='-')
    {
        printf("位置非空!请重新输入\n"); 
        return false;  
    }
    Board[row][col]=player;
    return true;
}

bool CheckIsDrawn(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '-')
            {
                return false;
            }
        }
    }
    return true;
}

bool IsVaildPlace(int row,int col)
{
    if (row < 0 || row >= Size || col < 0 || col >= Size)
    {
        return false;
    }
    return true;
}

// 解析刚下的一颗是否构成5颗
bool CheckIswin(char (*Board)[Size],int row,int col,char player)
{
    // 向量数组:4个方向；2个坐标(横+纵)
    int direction[4][2]=
    {
        {1,0},
        {1,1},
        {0,1},
        {-1,1}
    };
    //遍历四个方向：出现5个棋子则获胜
    for(int i=0;i<4;i++)
    {
        int count = 1;
        //下一颗棋子的方向
        int drow = row+direction[i][0];
        int dcol = col+direction[i][1];
        //两个while是并行的
        while(IsVaildPlace(drow,dcol)&&Board[drow][dcol]==player)//这个进入while循环的条件需要想清楚
        {
            count++;
            if(count==5)
            {
                return true;
            }
            drow = drow+direction[i][0];
            dcol = dcol+direction[i][1];   
        }
        //反方向找 
        drow = row-direction[i][0];
        dcol = col-direction[i][1];
        while(IsVaildPlace(drow,dcol)&&Board[drow][dcol]==player)
        {
            count++;
            if(count==5)
            {
                return true;
            }
            drow = drow-direction[i][0];
            dcol = dcol-direction[i][1]; 
        }
    }
    return false;
}

bool CheckIsCount(char (*Board)[Size],int row,int col,char player,int Num)
{
    //向量数组:4个方向；2个坐标(横+纵)
    int direction[4][2]=
    {
        {1,0},
        {1,1},
        {0,1},
        {-1,1}
    };
    //遍历四个方向：出现5个棋子则获胜
    for(int i=0;i<4;i++)
    {
        int count = 1;
        //下一颗棋子的方向
        int drow = row+direction[i][0];
        int dcol = col+direction[i][1];
        while(IsVaildPlace(drow,dcol)&&Board[drow][dcol]==player)
        {
            count++;
            if(count==Num)
            {
                return true;
            }
            drow = drow+direction[i][0];
            dcol = dcol+direction[i][1]; 
        }
        //反方向找
        drow = row-direction[i][0];
        dcol = col-direction[i][1];
        while(IsVaildPlace(drow,dcol)&&Board[drow][dcol]==player)
        {
            count++;
            if(count==Num)
            {
                return true;
            }
            drow = drow-direction[i][0];
            dcol = dcol-direction[i][1]; 
        }
    }
    return false;
}

bool AIMakeMove(char (*Board)[Size],int PlayerRow,int Playercol,char player,char AI)
{
    //智能决策 策略
    //优先取胜策略
    for(int i = 0;i<Size;i++)
    {
        for(int j=0;j<Size;j++)
        {
            if(Board[i][j]=='-')
            {
                Board[i][j]=AI;
                if(CheckIswin(Board,i,j,AI)==true)
                {
                    return true;//如果能赢，就下在这个位置
                }
                Board[i][j]='-';
            }
        }
    }
    //阻止对手策略：阻止对手赢
    for(int i = 0;i<Size;i++)
    {
        for(int j=0;j<Size;j++)
        {
            if(Board[i][j]=='-')
            {
                Board[i][j]=player;
                if((CheckIswin(Board,i,j,player)==true)
                 ||(CheckIsCount(Board,i,j,player,4)==true)
                 ||(CheckIsCount(Board,i,j,player,3)==true)
                 ||(CheckIsCount(Board,i,j,player,2)==true))
                {
                    Board[i][j]=AI;
                    return false;//如果能赢，就下在这个位置
                }
                Board[i][j]='-';
            }
        }
    }
    //随机策略
    // int direction[8][2]={0};
    // int count = 0;
}

void Single()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);

    char player = 'X';
    while(1)
    {
        PrintBoard(Board);
        int row,col;
        if(player=='X')
        {
            printf("请|%c|选手下棋",player);
            scanf("%d %d",&row,&col);
            if(MakeMove(Board,row-1,col-1,player)==false)
            {
                continue;
            }
        }
        else
        {
            printf("AI正在下棋...\n");
            if(AIMakeMove(Board,row-1,col-1,'X','O')==true)
            {
                PrintBoard(Board);
                printf("AI获胜\n");
                break;
            }
        }
        if(CheckIswin(Board,row-1,col-1,player)==true)
        {
            PrintBoard(Board);
            printf("恭喜|%c|选手获胜!\n",player);
            break;
        }
        if(CheckIsDrawn(Board)==true)
        {
            PrintBoard(Board);
            printf("平局!\n");
            break;
        }
        //切换玩家                                                                                                                                                   
        player = (player == 'X') ? 'O' : 'X';
    }
}

void Double()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);

    char player = 'X';
    while(1)
    {
        PrintBoard(Board);
        int row,col;
        printf("请|%c|选手下棋",player);
        scanf("%d %d",&row,&col);
        if(MakeMove(Board,row-1,col-1,player)==false)
        {
            continue;
        }
        if(CheckIswin(Board,row-1,col-1,player)==true)
        {
            PrintBoard(Board);
            printf("恭喜|%c|选手获胜!\n",player);
            break;
        }
        if(CheckIsDrawn(Board)==true)
        {
            PrintBoard(Board);
            printf("平局!\n");
            break;
        }
        //切换玩家                                                                                                                                                   
        player = (player == 'X') ? 'O' : 'X';
    }
}

int main(int argc,char* argv[])
{
    if(argc<2)
    {
        printf("缺少启动参数!\n");
        return 0;
    }

    if(strcmp(argv[1],"1")==0)
    {
        Single();
    }

    if(strcmp(argv[1],"2")==0)
    {
        Double();
    }
}
